/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.rbac.service.menu.impl;

import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.mvc.BaseMethodArgument;
import com.je.common.base.service.MetaService;
import com.je.common.base.service.PlatformService;
import com.je.common.base.service.rpc.SystemSettingRpcService;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.meta.rpc.develop.DevelopLogRpcService;
import com.je.rbac.exception.MenuException;
import com.je.rbac.service.grant.RbacGrantTopMenuPermissionService;
import com.je.rbac.service.menu.MenuService;
import com.je.rbac.service.menu.TopMenuService;
import com.je.rbac.service.permission.PermissionLoadService;
import com.je.servicecomb.CommonRequestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

@Service
public class TopMenuServiceImpl implements TopMenuService, CommonRequestService {

    @Autowired
    private MetaService metaService;
    @Autowired
    private RbacGrantTopMenuPermissionService rbacGrantTopMenuPermissionService;
    @Autowired
    private PlatformService manager;
    @Autowired
    private MenuService menuService;

    @Autowired
    private SystemSettingRpcService systemSettingRpcService;

    @Autowired
    private DevelopLogRpcService developLogRpcService;
    @Autowired
    private PermissionLoadService permissionLoadService;

    /**
     * 是否记录日志CODE
     */
    private static final String JE_SYS_DEVELOPLOG = "JE_SYS_DEVELOPLOG";

    @Override
    public DynaBean selectTopMenuById(String headMenuId) {
        return metaService.selectOne("JE_RBAC_HEADMENU", ConditionsWrapper.builder().eq("JE_RBAC_HEADMENU_ID", headMenuId));
    }

    @Override
    public List<DynaBean> selectTopMenuRelationByTopMenuId(String headMenuId) {
        return metaService.select("JE_RBAC_HEADMENU_RELATION", ConditionsWrapper.builder().eq("JE_RBAC_HEADMENU_ID", headMenuId));
    }

    @Override
    public List<DynaBean> selectTopMenuRelationByMenuId(List<String> menuIds) {
        return metaService.select("JE_RBAC_HEADMENU_RELATION", ConditionsWrapper.builder().in("RELATION_MENUMODULE_ID", menuIds));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateMenuRelation(List<String> topMenuIds) {
        for (String topMenuId : topMenuIds) {
            List<DynaBean> relationListBean = selectTopMenuRelationByTopMenuId(topMenuId);
            if (relationListBean != null && relationListBean.size() > 0) {
                for (DynaBean eachRelationBean : relationListBean) {
                    String menuId = eachRelationBean.getStr("RELATION_MENUMODULE_ID");
                    if (!Strings.isNullOrEmpty(menuId)) {
                        //删除顶部菜单关联表数据
                        menuService.doRemoveHeadMenuRelation(menuId, topMenuId);
                        //清空相关菜单 关联顶部菜单数据
                        menuService.updateTopMenuRelationBean(menuId, "", "");
                    }
                }
            }
        }
    }

    @Override
    public DynaBean selectTopMenuRelationById(String headMenuRelationId) {
        return metaService.selectOne("JE_RBAC_HEADMENU_RELATION", ConditionsWrapper.builder().eq("JE_RBAC_HEADMENU_RELATION_ID", headMenuRelationId));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public DynaBean doSave(BaseMethodArgument param, HttpServletRequest request) {
        DynaBean resultBean = manager.doSave(param, request);
        String seeRoleIds = resultBean.getStr("HEADMENU_SEEROLE_ID");
        String seeDeptIds = resultBean.getStr("HEADMENU_SEEDEPT_ID");
        String seeOrgIds = resultBean.getStr("HEADMENU_SEEORG_ID");
        String seeUserIds = resultBean.getStr("JE_RBAC_ACCOUNT_ID");
        updateSeeRolePermissions(resultBean.getStr("JE_RBAC_HEADMENU_ID"), "", seeRoleIds);
        updateSeeDeptPermissions(resultBean.getStr("JE_RBAC_HEADMENU_ID"), "", seeDeptIds);
        updateSeeOrgPermissions(resultBean.getStr("JE_RBAC_HEADMENU_ID"), "", seeOrgIds);
        updateSeeUserPermissions(resultBean.getStr("JE_RBAC_HEADMENU_ID"), "", seeUserIds);

        if (isLog()) {
            developLogRpcService.doDevelopLog("CREATE", "创建", "TOPMENU", "顶部菜单", resultBean.getStr("HEADMENU_NAME"), resultBean.getStr("HEADMENU_CODE"), resultBean.getStr("JE_RBAC_HEADMENU_ID"), resultBean.getStr("SY_PRODUCT_ID"));
        }
        return resultBean;
    }

    private Boolean isLog() {
        if ("1".equals(systemSettingRpcService.findSettingValue(JE_SYS_DEVELOPLOG))) {
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public DynaBean doUpdate(BaseMethodArgument param, HttpServletRequest request) {
        String pkId = getStringParameter(request, "JE_RBAC_HEADMENU_ID");
        String headmenuTypeCode = getStringParameter(request, "HEADMENU_TYPE_CODE");

        String targetSeeRoleIds = getStringParameter(request, "HEADMENU_SEEROLE_ID");
        String targetSeeDeptIds = getStringParameter(request, "HEADMENU_SEEDEPT_ID");
        String targetSeeOrgIds = getStringParameter(request, "HEADMENU_SEEORG_ID");
        String targetSeeUserIds = getStringParameter(request, "HEADMENU_SEEUSER_ID");

        DynaBean sourceBean = metaService.selectOneByPk("JE_RBAC_HEADMENU", pkId);
        String sourceSeeRoleIds = sourceBean.getStr("HEADMENU_SEEROLE_ID");
        String sourceSeeDeptIds = sourceBean.getStr("HEADMENU_SEEDEPT_ID");
        String sourceSeeOrgIds = sourceBean.getStr("HEADMENU_SEEORG_ID");
        String sourceSeeUserIds = sourceBean.getStr("HEADMENU_SEEUSER_ID");

        DynaBean updatedBean = manager.doUpdate(param, request);

        if (sourceBean.getStr("HEADMENU_TYPE_CODE").equals("MENU") && !headmenuTypeCode.equals("MENU")) {
            List<String> topMenuIds = new ArrayList<>();
            topMenuIds.add(pkId);
            updateMenuRelation(topMenuIds);
        }
        updateSeeRolePermissions(pkId, sourceSeeRoleIds, targetSeeRoleIds);
        updateSeeDeptPermissions(pkId, sourceSeeDeptIds, targetSeeDeptIds);
        updateSeeOrgPermissions(pkId, sourceSeeOrgIds, targetSeeOrgIds);
        updateSeeUserPermissions(pkId, sourceSeeUserIds, targetSeeUserIds);
        if (isLog()) {
            developLogRpcService.doDevelopLog("UPDATE", "更新", "TOPMENU", "顶部菜单", updatedBean.getStr("HEADMENU_NAME"), updatedBean.getStr("HEADMENU_CODE"), pkId, updatedBean.getStr("SY_PRODUCT_ID"));
        }
        return updatedBean;
    }

    @Override
    public void checkChildMenu(List<String> topMenuIds) throws MenuException {
        for (String topMenuId : topMenuIds) {
            List<DynaBean> relationListBean = selectTopMenuRelationByTopMenuId(topMenuId);
            if (relationListBean != null && relationListBean.size() > 0) {
                DynaBean topMenuBean = metaService.selectOneByPk("JE_RBAC_HEADMENU", topMenuId);
                if (topMenuIds.size() == 1) {
                    throw new MenuException("该顶部菜单存在关联菜单模块，请先移除！");
                } else {
                    throw new MenuException("该顶部菜单【" + topMenuBean.getStr("HEADMENU_NAME") + "】存在关联菜单模块，请先移除！");
                }
            }
        }
    }

    @Override
    public void updateSeeRolePermissions(String menuId, String sourceSeeRoleIds, String targetSeeRoleIds) {
        List<String> targetUpdateIds = new ArrayList<>();
        if (!Strings.isNullOrEmpty(targetSeeRoleIds)) {
            targetUpdateIds = new ArrayList<>(Splitter.on(",").splitToList(targetSeeRoleIds));
        }
        List<String> sourceUpdateIds = new ArrayList<>();
        if (!Strings.isNullOrEmpty(sourceSeeRoleIds)) {
            sourceUpdateIds = new ArrayList<>(Splitter.on(",").splitToList(sourceSeeRoleIds));
        }
        rbacGrantTopMenuPermissionService.removeTopMenuSeeRoles(menuId, sourceUpdateIds);
        rbacGrantTopMenuPermissionService.updateTopMenuSeeRoles(menuId, targetUpdateIds);
    }

    @Override
    public void updateSeeDeptPermissions(String menuId, String sourceSeeDeptIds, String targetSeeDeptIds) {
        List<String> targetUpdateIds = new ArrayList<>();
        if (!Strings.isNullOrEmpty(targetSeeDeptIds)) {
            targetUpdateIds = new ArrayList<>(Splitter.on(",").splitToList(targetSeeDeptIds));
        }
        List<String> sourceUpdateIds = new ArrayList<>();
        if (!Strings.isNullOrEmpty(sourceSeeDeptIds)) {
            sourceUpdateIds = new ArrayList<>(Splitter.on(",").splitToList(sourceSeeDeptIds));
        }
        rbacGrantTopMenuPermissionService.remoeveTopMenuSeeDepts(menuId, sourceUpdateIds);
        rbacGrantTopMenuPermissionService.updateTopMenuSeeDepts(menuId, targetUpdateIds);
    }

    @Override
    public void updateSeeOrgPermissions(String menuId, String sourceSeeOrgIds, String targetSeeOrgIds) {
        List<String> targetUpdateIds = new ArrayList<>();
        if (!Strings.isNullOrEmpty(targetSeeOrgIds)) {
            targetUpdateIds = new ArrayList<>(Splitter.on(",").splitToList(targetSeeOrgIds));
        }
        List<String> sourceUpdateIds = new ArrayList<>();
        if (!Strings.isNullOrEmpty(sourceSeeOrgIds)) {
            sourceUpdateIds = new ArrayList<>(Splitter.on(",").splitToList(sourceSeeOrgIds));
        }
        rbacGrantTopMenuPermissionService.removeTopMenuSeeOrgs(menuId, sourceUpdateIds);
        rbacGrantTopMenuPermissionService.updateTopMenuSeeOrgs(menuId, targetUpdateIds);
    }

    @Override
    public void updateSeeUserPermissions(String menuId, String sourceSeeUserIds, String targetSeeUserIds) {
        List<String> targetUpdateIds = new ArrayList<>();
        if (!Strings.isNullOrEmpty(targetSeeUserIds)) {
            targetUpdateIds = new ArrayList<>(Splitter.on(",").splitToList(targetSeeUserIds));
        }
        List<String> sourceUpdateIds = new ArrayList<>();
        if (!Strings.isNullOrEmpty(sourceSeeUserIds)) {
            sourceUpdateIds = new ArrayList<>(Splitter.on(",").splitToList(sourceSeeUserIds));
        }
        rbacGrantTopMenuPermissionService.removeTopMenuSeeUsers(menuId, sourceUpdateIds);
        rbacGrantTopMenuPermissionService.updateTopMenuSeeUsers(menuId, targetUpdateIds);
    }

    @Override
    public void saveDeleteLog(List<DynaBean> list) {
        for (DynaBean dynaBean : list) {
            if (isLog()) {
                developLogRpcService.doDevelopLog("UPDATE", "更新", "TOPMENU", "顶部菜单", dynaBean.getStr("HEADMENU_NAME"), dynaBean.getStr("HEADMENU_CODE"), dynaBean.getStr("JE_RBAC_HEADMENU_ID"), dynaBean.getStr("SY_PRODUCT_ID"));
            }
        }
    }

}
